#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include "TestLogger.h"

typedef struct _TestModule {
	_TestModule* fNextModule;
	const _TCHAR* ctstrModuleName;
	bool (*fTestModule)();
	bool bSucceed;
} TestModule;

class TestRunner {
private :
	TestModule* m_fFirstModule;
	TestModule* m_fLastModule;
public :
	TestRunner();
	~TestRunner();
	void addTest(const _TCHAR* a_ctstrModuleName, bool (*a_fTestModule)());
	void executeTest();
	int getTotalCount();
	int getSucceedCount();
	int getFailedCount();
	void getFailedModuleNames(const _TCHAR** a_ctstrFailedNames, const int a_nFailedNameCount);
};

TestRunner::TestRunner() {
	m_fFirstModule = NULL;
	m_fLastModule = NULL;
}

TestRunner::~TestRunner() {
	while(m_fFirstModule != NULL) {
		TestModule* deletingModule = m_fFirstModule;
		m_fFirstModule = m_fFirstModule->fNextModule;
		delete deletingModule;
	}
	m_fFirstModule = NULL;
	m_fLastModule = NULL;
}

void TestRunner::addTest(const _TCHAR* a_ctstrModuleName, bool (*a_fTestModule)()) {
	TestModule* module = new TestModule;
	module->fNextModule = NULL;
	module->ctstrModuleName = a_ctstrModuleName;
	module->fTestModule = a_fTestModule;
	module->bSucceed = false;

	if(m_fLastModule == NULL) {
		m_fFirstModule = module;
		m_fLastModule = module;
	}
	else {
		m_fLastModule->fNextModule = module;
		m_fLastModule = module;
	}

}

void TestRunner::executeTest(){

	TestModule* fTestingModule = m_fFirstModule;

	while(fTestingModule != NULL) {
		fTestingModule->bSucceed = fTestingModule->fTestModule();
		fTestingModule = fTestingModule->fNextModule;
	}
}
int TestRunner::getTotalCount(){
	TestModule* fTestingModule = m_fFirstModule;

	int totalCount = 0;
	while(fTestingModule != NULL) {
		totalCount++;
		fTestingModule = fTestingModule->fNextModule;
	}

	return totalCount;
}
int TestRunner::getSucceedCount(){
	TestModule* fTestingModule = m_fFirstModule;

	int succeedCount = 0;
	while(fTestingModule != NULL) {
		if(fTestingModule->bSucceed) {
			succeedCount++;
		}
		fTestingModule = fTestingModule->fNextModule;
	}

	return succeedCount;
}
int TestRunner::getFailedCount(){
	TestModule* fTestingModule = m_fFirstModule;

	int failedCount = 0;
	while(fTestingModule != NULL) {
		if(fTestingModule->bSucceed == false) {
			failedCount++;
		}
		fTestingModule = fTestingModule->fNextModule;
	}

	return failedCount;
}
void TestRunner::getFailedModuleNames(const _TCHAR** a_ctstrFailedNames, const int a_nFailedNameCount){
	int failedCount = getFailedCount();
	if(a_nFailedNameCount > failedCount) {
		return;
	}

	TestModule* fTestingModule = m_fFirstModule;

	int failedIndex = -1;
	while(fTestingModule != NULL) {
		if(fTestingModule->bSucceed == false) {
			a_ctstrFailedNames[++failedIndex] = fTestingModule->ctstrModuleName;
		}
		fTestingModule = fTestingModule->fNextModule;
	}
}